package rs.udd.web.controller;

import static rs.udd.service.util.SecurityUtil.ADMIN_ROLE_ONLY;
import static rs.udd.service.util.SecurityUtil.ADVERTISER_ROLE_ONLY;

import java.io.File;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import rs.udd.exceptions.UddException;
import rs.udd.model.Advert;
import rs.udd.model.Advertiser;
import rs.udd.service.AdvertService;
import rs.udd.service.AdvertiserService;
import rs.udd.service.ApplyAdvertService;
import rs.udd.service.dto.advert.AdvertDto;
import rs.udd.service.dto.advert.AdvertViewDto;
import rs.udd.service.dto.advert.ApplyAdvertDto;
import rs.udd.service.util.FileUtil;
import rs.udd.service.util.FileUtil.FileTypes;
import rs.udd.service.util.SecurityUtil;

@Controller
@RequestMapping({ "/adverts", "/adverts/" })
public class AdvertController {

	private final Logger LOGGER = LogManager.getLogger(getClass());

	@Autowired
	private AdvertService advertService;
	
	@Autowired
	private AdvertiserService advertiserService;

	@Autowired
	private ApplyAdvertService applyAdvertService;

	@RequestMapping(value = "/view/{id}", method = RequestMethod.GET)
	public String view(Model model, @PathVariable("id") Long id) {

		LOGGER.info("Requesting to view advert with '" + id + "'");

		try {
			AdvertViewDto dto = advertService.findOneForViewing(id);

			if (dto == null) {
				LOGGER.error("Advert with '" + id + "' donesn't exist.");
				return "error/404";
			}

			LOGGER.info("Viewing advert..." + dto);
			model.addAttribute("viewedAdvert", dto);
			
			boolean agentApplied = applyAdvertService.checkIfAgentApplied(id);
			model.addAttribute("agentApplied", agentApplied);
			model.addAttribute("applyAdvertDto", new ApplyAdvertDto());

			return "advert/viewAdvert";
		} catch (UddException e) {
			LOGGER.error("Error while requesting view of advert with '" + id + "'", e);
			model.addAttribute("message", e.getMessage());
			return "error/error";
		}
	}
	
	@PreAuthorize(ADVERTISER_ROLE_ONLY)
	@RequestMapping(value = "/editAdvert/{id}", method = RequestMethod.GET)
	public String handleEditGet(@PathVariable Long id, Model model, Authentication authentication) throws UddException {

		AdvertViewDto advertViewDto = advertService.findOneForViewing(id);
		model.addAttribute("editedAdvert", advertViewDto);

		return "advert/editAdvert";
	}

	@PreAuthorize(ADVERTISER_ROLE_ONLY)
	@RequestMapping(value = "/editAdvert", method = RequestMethod.POST)
	public String handleEditPost(@ModelAttribute("editedAdvert") AdvertDto dto, BindingResult result, Model model,
			Authentication authentication, HttpSession session) {
		
		//TODO: complete delete of the advert (two fields that are visible on the form and upload of a new pdf file, with following indexing and DB change)
		
		if (result.hasErrors()) {

			LOGGER.error("Binding error,");
			LOGGER.error(result);

			return "agent/editAgent";
		}

		LOGGER.info("Editing advert...");
		try {
			File file = (File) session.getAttribute("uploadedFile");
			if (file != null) {
				session.setAttribute("uploadedFile", null);
			}
			
			dto = advertService.edit(dto, file);
			if (dto.isEmpty()) {
				Advertiser advertiser = advertiserService.getLoggedAdvertiser();
				String fileName = FileUtil.getFolderPathForAdvert(
						advertiser.getUsername(), FileTypes.ADVERT) + dto.getFile().getOriginalFilename();
				fileName = FileUtil.generateFileName(fileName);
				File convFile = new File(fileName);
				dto.getFile().transferTo(convFile);
				
				model.addAttribute("advert", dto);
				session.setAttribute("uploadedFile", convFile);
				LOGGER.warn("Metadata missing...");
				return "advert/addMetadata";
			} else {
				LOGGER.info("Advert edited successfully");
				// when posting a successful form to controller, always do redirect after. google post-get-redirect for a reason.
				return "redirect:/home";
			}
		} catch (Exception e) {
			LOGGER.error("Error while requesting edit agent.", e);
			model.addAttribute("message", e.getMessage());
			return "error/error";
		}
	}
	
	@PreAuthorize(ADVERTISER_ROLE_ONLY)
	@RequestMapping(value = "/deleteAdvert/{id}", method = RequestMethod.GET)
	public String deleteAdvert(@PathVariable Long id, Model model, HttpServletResponse resp) throws UddException {
		advertService.delete(id);
		
		Advertiser advertiser = advertiserService.getLoggedAdvertiser();
		
		model.addAttribute("adverts", advertiser.getAdverts());

		return "/advertiser/myAdverts";
	}
	
	@PreAuthorize(ADMIN_ROLE_ONLY)
	@RequestMapping(value = "/deleteAdvertFromAdmin/{id}", method = RequestMethod.GET)
	public String deleteAdvertFromAdmin(@PathVariable Long id, Model model, HttpServletResponse resp) throws UddException {
		Advert advert = advertService.findOne(id);
		
		advertService.delete(id);

		return "redirect:/advertisers/view/"+advert.getAdvertiser().getId();
	}
	
	@PreAuthorize(SecurityUtil.AGENT_ROLE_ONLY)
	@RequestMapping(value = "/view/{id}/apply", method = RequestMethod.POST)
	public String apply(@PathVariable("id") Long advertId, @ModelAttribute("applyAdvertDto") ApplyAdvertDto applyAdvertDto) {
		applyAdvertService.apply(advertId, applyAdvertDto);
		return "redirect:/home";
	}
}
